package nhatquang.gs.controler;

import java.util.Random;
import java.util.Stack;

import org.andengine.entity.Entity;
import org.andengine.entity.modifier.MoveModifier;
import org.andengine.entity.modifier.ScaleModifier;
import org.andengine.entity.sprite.AnimatedSprite;
import org.andengine.entity.sprite.Sprite;

import android.util.Log;

import nhatquang.gs.model.Fruit;
import nhatquang.gs.model.Public;
import nhatquang.gs.view.PlayerScene;

public class FruitManager {
	public static final FruitManager INSTANCE = new FruitManager();
	private ResourcesManager resourcesManager = ResourcesManager.getInstance();

	public boolean isUpdateScore = false;
	public boolean mOpenGame = true;
	private int level = 0;

	public Fruit[][] mapFruit;
	public boolean[][] scale;

	public Stack<Fruit> stack;
	public int[][] register;

	public int score = 0;
	public int sumFruit = 0;
	public int sumMove = 0;

	private PlayerScene scene;
	private Entity mEntityFruit;

	public static FruitManager getINSTANCE() {
		return INSTANCE;
	}

	public void initial(int numberFruit, PlayerScene scene, Entity mEntityFruit) {

		mapFruit = new Fruit[7][7];
		scale = new boolean[7][7];

		stack = new Stack<Fruit>();
		register = new int[2][7];

		this.scene = scene;
		this.level = numberFruit;

		for (int i = 0; i < 7; i++) {
			for (int j = 0; j < 7; j++) {
				mapFruit[i][j] = randomSprite(numberFruit, convertX(j), -490
						+ i * 70, i, j, convertY(i));
				scene.attachChild(mapFruit[i][j]);
			}
		}

	}

	public void checkFruit(Fruit fruit) {
		if (!mOpenGame)
			return;
		int row = fruit.getRow();
		int collumn = fruit.getCollumn();

		/*-----------if stack empty---------------*/
		if (stack.empty()) {
			stack.add(fruit);
			scale[row][collumn] = true;
			fruit.stateSell();
			sumFruit += 1;
			registerCollumn(row, collumn);
			return;
		}

		if (stack.peek().equals(fruit)) {
			return;
		}

		/*--------------check bien-----------------*/
		int rowold = stack.peek().getRow();
		int collumnold = stack.peek().getCollumn();
		if (((rowold - 1) == row && collumnold == collumn)
				|| (rowold + 1 == row && collumnold == collumn)
				|| (rowold == row && collumnold - 1 == collumn)
				|| (rowold == row && collumnold + 1 == collumn)
				|| (rowold - 1 == row && collumnold + 1 == collumn)
				|| (rowold - 1 == row && collumnold - 1 == collumn)
				|| (rowold + 1 == row && collumnold - 1 == collumn)
				|| (rowold + 1 == row && collumnold + 1 == collumn)) {

			/*--------------nam trong bien ---------------*/
			if (fruit.getSpecies() != stack.peek().getSpecies()) {
				return;
			}

			/*--------------check scale-------------------*/
			if (!scale[row][collumn]) {
				stack.add(fruit);
				scale[row][collumn] = true;
				fruit.stateSell();
				sumFruit += 1;
				registerCollumn(row, collumn);
				Log.d("nhat quang",
						"hoa qua moi chua scale ---------------------");
				return;
			}

			/*---------------quay lui duong----------------*/
			while (!stack.peek().equals(fruit)) {
				Log.d("nhat quang",
						"quay lui $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$");
				try {
					int m = stack.peek().getRow();
					int n = stack.peek().getCollumn();
					unregisterCollumn(m, n);
					scale[m][n] = false;
					stack.pop().stateNormall();
				} catch (Exception ok) {
					Log.d("nhat quang",
							"da xay ra loi tai ham checkFruit +++++++++++++++++++++++++++++++++++++");
				}
				sumFruit -= 1;
			}
			return;
		}

		/*-----------------da vuot bien------------------*/
		updateGame();

		return;
	}

	public void updateGame() {
		mOpenGame = false;
		if (sumFruit > 1) {
			while (!stack.empty()) {
				scene.detachChild(stack.peek());
				scene.unregisterTouchArea(stack.pop().getFruitNomall());
			}

			updateArray();
			if (sumFruit == 2) {
				score -= 10;
				if (score < 0)
					score = 0;
				scene.updateScore(score);
			} else {
				score += 5 * sumFruit;
				scene.updateScore(score);
			}

			sumFruit = 0;
			mOpenGame = true;
			return;
		}
		while (!stack.empty()) {
			int row = stack.peek().getRow();
			int collumn = stack.peek().getCollumn();

			register[0][collumn] = 0;
			register[1][collumn] = 0;

			scale[row][collumn] = false;
			stack.pop().stateNormall();
			
			sumFruit = 0;
		}
		for (int i = 0; i < 7; i++) {
			register[0][i] = 0;
			register[1][i] = 0;
		}
		mOpenGame = false;
	}

	public void updateArray() {
		int ok = 0;
		long T1, T2;
		T1 = System.currentTimeMillis();
		for (int i = 0; i < 7; i++) {
			if (register[0][i] != 0) {
				int last = register[1][i];
				int swap = last - 1;
				while (last >= 0) {
					while (swap >= 0 && scale[swap][i])
						swap -= 1;
					if (swap >= 0 && !scale[swap][i]) {
						moveSmooth(mapFruit[swap][i], last, i);
						swap -= 1;
						last -= 1;
						ok = last;
						continue;
					}
					mapFruit[last][i] = randomSprite(level, convertX(i), -70
							* (ok - last + 1), last, i, convertY(last));
					scene.attachChild(mapFruit[last][i]);
					scale[last][i] = false;

					last -= 1;
				}

				register[0][i] = 0;
				register[1][i] = 0;
			}
		}
		Log.d("",
				"TONG THOI GIAN TRONG VONG FOR :"
						+ Long.toString(System.currentTimeMillis() - T1));
	}

	public void registerCollumn(int row, int collumn) {
		switch (collumn) {
		case 0: {
			register[0][0] += 1;
			if (register[1][0] <= row)
				register[1][0] = row;
			// Log.d("nhat quang", "thay doi tren cot " + Integer.toString(0));
		}
			break;
		case 1: {
			register[0][1] += 1;
			if (register[1][1] <= row)
				register[1][1] = row;
			// Log.d("nhat quang", "thay doi tren cot " + Integer.toString(1));
		}
			break;
		case 2: {
			register[0][2] += 1;
			if (register[1][2] <= row)
				register[1][2] = row;
			// Log.d("nhat quang", "thay doi tren cot " + Integer.toString(2));
		}
			break;
		case 3: {
			register[0][3] += 1;
			if (register[1][3] <= row)
				register[1][3] = row;
			// Log.d("nhat quang", "thay doi tren cot " + Integer.toString(3));
		}
			break;
		case 4: {
			register[0][4] += 1;
			if (register[1][4] <= row)
				register[1][4] = row;
			// Log.d("nhat quang", "thay doi tren cot " + Integer.toString(4));
		}
			break;
		case 5: {
			register[0][5] += 1;
			if (register[1][5] <= row)
				register[1][5] = row;
			// Log.d("nhat quang", "thay doi tren cot " + Integer.toString(5));
		}
			break;
		case 6: {
			register[0][6] += 1;
			if (register[1][6] <= row)
				register[1][6] = row;
			// Log.d("nhat quang", "thay doi tren cot " + Integer.toString(6));
		}
			break;
		}
	}

	private void unregisterCollumn(int m, int n) {
		register[0][n] -= 1;
		int minIndex = 0;
		for (int i = 0; i < 7; i++) {
			if (i == m)
				continue;
			if (scale[i][n] && i >= minIndex)
				minIndex = i;
		}
		register[1][n] = minIndex;
	}

	public void moveSmooth(Fruit entity, int endM, int endN) {

		float currentX = entity.getX();
		float currentY = entity.getY();

		int currentRow = entity.getRow();
		int currentCollumn = entity.getCollumn();

		float endY = convertY(endM);
		float duration = (endY - currentY) / Public.SPEED_SPRITE;

		MoveModifier move = new MoveModifier(duration, currentX, currentX,
				currentY, endY);
		entity.registerEntityModifier(move);

		entity.setRow(endM);
		entity.setCollumn(endN);

		scale[endM][endN] = false;
		mapFruit[endM][endN] = entity;

		mapFruit[currentRow][currentCollumn] = null;
		scale[currentRow][currentCollumn] = false;

		System.gc();
	}

	public Fruit randomSprite(int numberFruit, float x, float y, int row,
			int collumn, float endY) {

		int indext = new Random().nextInt(numberFruit);

		switch (indext) {

		case 0: {
			return new Fruit(x, y, row, collumn,
					resourcesManager.mTextureRegionFruit[0],
					resourcesManager.mTextureRegionFruitSell[0], endY, 0, scene);
		}
		case 1: {
			return new Fruit(x, y, row, collumn,
					resourcesManager.mTextureRegionFruit[1],
					resourcesManager.mTextureRegionFruitSell[1], endY, 1, scene);
		}
		case 2: {
			return new Fruit(x, y, row, collumn,
					resourcesManager.mTextureRegionFruit[2],
					resourcesManager.mTextureRegionFruitSell[2], endY, 2, scene);
		}
		case 3: {
			return new Fruit(x, y, row, collumn,
					resourcesManager.mTextureRegionFruit[3],
					resourcesManager.mTextureRegionFruitSell[3], endY, 3, scene);
		}
		case 4: {
			return new Fruit(x, y, row, collumn,
					resourcesManager.mTextureRegionFruit[4],
					resourcesManager.mTextureRegionFruitSell[4], endY, 4, scene);
		}
		case 5: {
			return new Fruit(x, y, row, collumn,
					resourcesManager.mTextureRegionFruit[5],
					resourcesManager.mTextureRegionFruitSell[5], endY, 5, scene);
		}
		case 6: {
			return new Fruit(x, y, row, collumn,
					resourcesManager.mTextureRegionFruit[6],
					resourcesManager.mTextureRegionFruitSell[6], endY, 6, scene);
		}
		case 7: {
			return new Fruit(x, y, row, collumn,
					resourcesManager.mTextureRegionFruit[7],
					resourcesManager.mTextureRegionFruitSell[7], endY, 7, scene);
		}

		}

		return null;
	}

	public void changeFruit(int row, int collumn, float x, float y) {
		mEntityFruit.detachChild(mapFruit[row][collumn]);
		// mapFruit[row][collumn].setVisible(false);
		Sprite test = new Sprite(x, y,
				ResourcesManager.INSTANCE.mTextureRegionFruitSell[0],
				ResourcesManager.INSTANCE.VBOM);
		test.registerEntityModifier(new ScaleModifier(0.5f, 1, 1.5f));
		mEntityFruit.attachChild(test);
	}

	public void detackModifier(AnimatedSprite animatedSprite) {
		scene.detachChild(animatedSprite);
	}

	public float convertX(int m) {
		return m * Public.WIDTH_SCREEN / 7 + 1;
	}

	public float convertY(int n) {
		return n * (Public.HEIGHT_SCREEN - Public.HEIGHT_MENU) / 7
				+ Public.HEIGHT_MENU;
	}

}
